package net.homeip.dometec.autodownloadrcsqt;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import net.homeip.dometec.autodownloadrcsqt.utils.FileUtils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicNameValuePair;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class HttpAccess {

	public static final String URL_LOGIN = "http://inapp.rcs.it/inapp3/services/csg/login";
	public static final String APPID = "edicolacorsera";

	private final String cli;
	private final String group;
	private final String hostTestata;
	private String hostSession;
	private String hostPdf;
	private DefaultHttpClient httpClient;
	private DocumentBuilderFactory factory;
	private CookieStore cookieStore;
	private String parSessionID;
	private String hsc;

	public HttpAccess(String cli, String group, String hostTestata) throws IOException {

		this.cli = cli;
		this.group = group;
		this.hostTestata = hostTestata;

		hostSession = "http://sfoglia2" + hostTestata + "/SIPOL_RCS/?cli=" + cli + "&group=" + group;
		hostPdf = "http://sfoglia2" + hostTestata + "/SIPOL_RCS/main";

		httpClient = new DefaultHttpClient();
		httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BEST_MATCH);

		cookieStore = new BasicCookieStore();
		httpClient.setCookieStore(cookieStore);

		factory = DocumentBuilderFactory.newInstance();
		factory.setValidating(false);

	}

	public boolean autentica(String username, String password) throws Exception {

		List<NameValuePair> parameters = new ArrayList<>();
		parameters.add(new BasicNameValuePair("appid", APPID));
		parameters.add(new BasicNameValuePair("username", username));
		parameters.add(new BasicNameValuePair("password", password));
		HttpEntity entity = new UrlEncodedFormEntity(parameters);
		HttpPost post = new HttpPost(URL_LOGIN);
		post.setEntity(entity);

		HttpResponse execute = httpClient.execute(post);
		HttpEntity httpEntity = execute.getEntity();
		post.releaseConnection();

		if (execute.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
			return false;

		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(httpEntity.getContent());

		String userid = document.getDocumentElement().getElementsByTagName("runaid").item(0).getTextContent();

		BasicClientCookie cookie = new BasicClientCookie("RCSEOL", userid);
		cookie.setDomain(hostTestata);
		cookie.setVersion(0);
		cookie.setPath("/");
		cookieStore.addCookie(cookie);

		return true;

	}

	public boolean openSession() throws Exception {

		HttpGet get = new HttpGet(hostSession);
		HttpResponse execute = httpClient.execute(get);
		get.releaseConnection();

		if (execute.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
			return false;

		// RECUPERO H_S_C
		List<NameValuePair> parameters = new ArrayList<>();
		parameters.add(new BasicNameValuePair("fn", "start"));
		parameters.add(new BasicNameValuePair("profile", "start"));
		parameters.add(new BasicNameValuePair("cli", cli));
		parameters.add(new BasicNameValuePair("demoday", "null"));
		parameters.add(new BasicNameValuePair("group", group));
		parameters.add(new BasicNameValuePair("paper", "null"));
		parameters.add(new BasicNameValuePair("CDPU", "null"));
		HttpEntity entity = new UrlEncodedFormEntity(parameters);
		HttpPost post = new HttpPost(hostPdf);
		post.setEntity(entity);
		execute = httpClient.execute(post);
		String out = FileUtils.convertStreamToString(execute.getEntity().getContent());
		post.releaseConnection();

		if (execute.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
			return false;

		Pattern pattern = Pattern.compile("H_S_C=([^&\"]*)");
		Matcher matcher = pattern.matcher(out);
		matcher.find();
		hsc = matcher.group(1);

		pattern = Pattern.compile("[^\"]*showMainContainer[^\"]*");
		matcher = pattern.matcher(out);
		matcher.find();
		String nextUrl = matcher.group(0);

		// RECUPERO parSessionID
		get = new HttpGet(nextUrl);
		execute = httpClient.execute(get);
		out = FileUtils.convertStreamToString(execute.getEntity().getContent());
		get.releaseConnection();

		if (execute.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
			return false;

		pattern = Pattern.compile("m_sParSessionID\\s*=\\s*(\"[^\"]*)");
		matcher = pattern.matcher(out);
		matcher.find();
		parSessionID = matcher.group(1);

		return true;

	}

	// Tutte le ultime edizioni disponibili
	public List<Map<String, String>> getPubblicazioniEdizioni() throws Exception {

		List<NameValuePair> parameters = new ArrayList<>();
		parameters.add(new BasicNameValuePair("fn", "getPubblicazioniEdizioni"));
		parameters.add(new BasicNameValuePair("profile", "start"));
		parameters.add(new BasicNameValuePair("H_S_C", hsc));
		HttpEntity entity = new UrlEncodedFormEntity(parameters);
		HttpPost post = new HttpPost(hostPdf);
		post.setEntity(entity);

		HttpResponse execute = httpClient.execute(post);

		HttpEntity httpEntity = execute.getEntity();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(httpEntity.getContent());
		post.releaseConnection();

		if (execute.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
			return null;

		List<Map<String, String>> edizioni = new ArrayList<>();

		NodeList elementsByTagName = document.getDocumentElement().getElementsByTagName("R");
		for (int i = 0; i < elementsByTagName.getLength(); i++) {
			Node item = elementsByTagName.item(i);
			NodeList childNodes = item.getChildNodes();
			Map<String, String> map = new HashMap<>();
			for (int j = 0; j < childNodes.getLength(); j++) {
				Node child = childNodes.item(j);
				map.put(child.getAttributes().getNamedItem("n").getNodeValue(), child.getTextContent());
			}

			if ("NAZIONALE".equalsIgnoreCase(map.get("EDIZIONE_INTERNA")) || "ECONOMIA".equalsIgnoreCase(map.get("EDIZIONE_INTERNA"))
					|| "MILANO".equalsIgnoreCase(map.get("EDIZIONE_INTERNA"))
					|| map.get("EDIZIONE_INTERNA").equalsIgnoreCase(map.get("TESTATA_ESTESA")))
				edizioni.add(map);

		}

		return edizioni;

	}

	public boolean getPdf(File outfile, String testata, String edizione, String data, JFrame mainWindow, JProgressBar progressBar)
			throws Exception {

		List<NameValuePair> parameters = new ArrayList<>();
		parameters.add(new BasicNameValuePair("fn", "getFileToSave"));
		parameters.add(new BasicNameValuePair("Cod_Testata", testata));
		parameters.add(new BasicNameValuePair("Cod_Edizione", edizione));
		parameters.add(new BasicNameValuePair("Data_pubb", data));
		parameters.add(new BasicNameValuePair("fileType", "ALL"));
		parameters.add(new BasicNameValuePair("profile", "start"));
		parameters.add(new BasicNameValuePair("H_S_C", parSessionID));

		HttpEntity entity = new UrlEncodedFormEntity(parameters);
		HttpPost post = new HttpPost(hostPdf);
		post.setEntity(entity);

		HttpResponse execute = httpClient.execute(post);

		HttpEntity httpEntity = execute.getEntity();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document document = builder.parse(httpEntity.getContent());
		post.releaseConnection();

		if (execute.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
			return false;

		Map<String, String> params = new HashMap<>();
		NodeList childNodes = document.getDocumentElement().getFirstChild().getChildNodes();
		for (int i = 0; i < childNodes.getLength(); i++)
			params.put(childNodes.item(i).getAttributes().getNamedItem("n").getTextContent(), childNodes.item(i).getTextContent());

		parameters = new ArrayList<>();
		parameters.add(new BasicNameValuePair("fn", "getFileStream"));
		parameters.add(new BasicNameValuePair("par", params.get("Par_call_getFileStream")));
		parameters.add(new BasicNameValuePair("H_S_C", ""));
		entity = new UrlEncodedFormEntity(parameters);
		post = new HttpPost(hostPdf);
		post.setEntity(entity);

		BasicClientCookie cookie = new BasicClientCookie("COOKIE_NAME_DOWNLOAD_APPEND", params.get("cookie_download_append"));
		cookie.setDomain("sfoglia2" + hostTestata);
		cookieStore.addCookie(cookie);

		execute = httpClient.execute(post);
		InputStream pdfStream = execute.getEntity().getContent();

		progressBar.setMaximum((int) execute.getEntity().getContentLength());
		progressBar.setValue(0);

		FileOutputStream file = new FileOutputStream(outfile);

		byte buf[] = new byte[1024];
		int len;
		while ((len = pdfStream.read(buf)) > 0) {
			file.write(buf, 0, len);
			progressBar.setValue(progressBar.getValue() + len);
			mainWindow.repaint();
		}
		file.close();
		pdfStream.close();

		progressBar.setValue(progressBar.getMaximum());

		post.releaseConnection();

		if (execute.getStatusLine().getStatusCode() != HttpStatus.SC_OK)
			return false;

		return true;
	}
}
